View Javadoc
1   package edu.jiangxin.apktoolbox.main;
2   
3   import edu.jiangxin.apktoolbox.Version;
4   import edu.jiangxin.apktoolbox.convert.base.BaseConvertPanel;
5   import edu.jiangxin.apktoolbox.convert.color.ColorConvertPanel;
6   import edu.jiangxin.apktoolbox.convert.color.ColorPickerPanel;
7   import edu.jiangxin.apktoolbox.convert.protobuf.unsupervised.ProtobufConvertPanel;
8   import edu.jiangxin.apktoolbox.convert.relationship.RelationShipConvertPanel;
9   import edu.jiangxin.apktoolbox.convert.time.TimeConvertPanel;
10  import edu.jiangxin.apktoolbox.convert.zh2unicode.Zh2UnicodeConvertPanel;
11  import edu.jiangxin.apktoolbox.android.dumpsys.alarm.DumpsysAlarmPanel;
12  import edu.jiangxin.apktoolbox.file.batchrename.BatchRenamePanel;
13  import edu.jiangxin.apktoolbox.file.EncodeConvertPanel;
14  import edu.jiangxin.apktoolbox.file.OsConvertPanel;
15  import edu.jiangxin.apktoolbox.file.checksum.ChecksumPanel;
16  import edu.jiangxin.apktoolbox.file.password.recovery.RecoveryPanel;
17  import edu.jiangxin.apktoolbox.file.duplicate.DuplicateSearchPanel;
18  import edu.jiangxin.apktoolbox.file.zhconvert.ZhConvertPanel;
19  import edu.jiangxin.apktoolbox.help.*;
20  import edu.jiangxin.apktoolbox.android.i18n.I18nAddPanel;
21  import edu.jiangxin.apktoolbox.android.i18n.I18nFindLongestPanel;
22  import edu.jiangxin.apktoolbox.android.i18n.I18nRemovePanel;
23  import edu.jiangxin.apktoolbox.android.monkey.MonkeyPanel;
24  import edu.jiangxin.apktoolbox.help.settings.SettingsPanel;
25  import edu.jiangxin.apktoolbox.reverse.*;
26  import edu.jiangxin.apktoolbox.android.screenshot.ScreenShotPanel;
27  import edu.jiangxin.apktoolbox.reverse.ApktoolPanel;
28  import edu.jiangxin.apktoolbox.swing.extend.EasyFrame;
29  import edu.jiangxin.apktoolbox.swing.extend.EasyPanel;
30  import edu.jiangxin.apktoolbox.swing.extend.listener.ChangeMenuListener;
31  import edu.jiangxin.apktoolbox.swing.extend.listener.ChangeMenuToUrlListener;
32  import edu.jiangxin.apktoolbox.swing.extend.listener.IPreChangeMenuCallBack;
33  import edu.jiangxin.apktoolbox.swing.extend.plugin.ChangeMenuPreparePluginController;
34  import edu.jiangxin.apktoolbox.swing.extend.plugin.PluginPanel;
35  import edu.jiangxin.apktoolbox.utils.Utils;
36  import org.apache.commons.configuration2.Configuration;
37  import org.apache.commons.lang3.StringUtils;
38  import org.apache.logging.log4j.LogManager;
39  import org.apache.logging.log4j.Logger;
40  
41  import javax.swing.*;
42  import javax.swing.border.EmptyBorder;
43  import java.awt.*;
44  import java.awt.event.*;
45  import java.io.Serial;
46  import java.lang.reflect.InvocationTargetException;
47  import java.text.MessageFormat;
48  import java.util.Locale;
49  import java.util.Objects;
50  
51  /**
52   * @author jiangxin
53   * @author 2018-08-19
54   */
55  public class MainFrame extends EasyFrame {
56  
57      @Serial
58      private static final long serialVersionUID = 1L;
59  
60      private JPanel contentPane;
61      private JMenuBar menuBar;
62  
63      public static void main(String[] args) {
64          final Logger logger = LogManager.getLogger(MainFrame.class.getSimpleName());
65          boolean isEnvironmentOk = Utils.checkAndInitEnvironment();
66          if (!isEnvironmentOk) {
67              logger.error("Environment is not ready, exit");
68              return;
69          }
70          EventQueue.invokeLater(() -> {
71              Configuration conf = Utils.getConfiguration();
72              String lookAndFeelClassName = conf.getString("look.and.feel.class.name");
73              if (StringUtils.isEmpty(lookAndFeelClassName)) {
74                  lookAndFeelClassName = "com.formdev.flatlaf.FlatDarculaLaf";
75                  conf.setProperty("look.and.feel.class.name", lookAndFeelClassName);
76              }
77              try {
78                  UIManager.setLookAndFeel(lookAndFeelClassName);
79              } catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {
80                  logger.error("setLookAndFeel failed, use default instead", e);
81              }
82  
83              String currentLocaleLanguage = conf.getString("locale.language");
84              if (StringUtils.isEmpty(currentLocaleLanguage)) {
85                  currentLocaleLanguage = Locale.ENGLISH.getLanguage();
86                  conf.setProperty("locale.language", currentLocaleLanguage);
87              }
88              Locale.setDefault(new Locale(currentLocaleLanguage));
89  
90              MainFrame frame = new MainFrame();
91  
92              boolean isAlwaysOnTop = conf.getBoolean("always.on.top", false);
93              conf.setProperty("always.on.top", isAlwaysOnTop);
94              frame.setAlwaysOnTop(isAlwaysOnTop);
95  
96              frame.setVisible(true);
97          });
98      }
99  
100     public MainFrame() {
101         super();
102         if (SystemTray.isSupported()) {
103             configSystemTray();
104         }
105 
106         setTitle(MessageFormat.format(bundle.getString("main.title"), Version.VERSION));
107         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
108         setMenuBar();
109         contentPane = new JPanel();
110         contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
111         contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
112         contentPane.add(Box.createVerticalGlue());
113         EasyPanel initPanel = new AboutPanel();
114         initPanel.init();
115         initPanel.setBorder(BorderFactory.createTitledBorder(bundle.getString("help.about.title")));
116         contentPane.add(initPanel);
117         contentPane.add(Box.createVerticalGlue());
118         setContentPane(contentPane);
119         refreshSizeAndLocation();
120     }
121 
122     private void configSystemTray() {
123         SystemTray systemTray = SystemTray.getSystemTray();
124         PopupMenu popupMenu = new PopupMenu();
125         final MenuItem show = new MenuItem("Open");
126         final MenuItem exit = new MenuItem("Close");
127         ActionListener actionListener = e -> {
128             if (e.getSource() == show) {
129                 setExtendedState(JFrame.NORMAL);
130                 setVisible(true);
131             }
132             if (e.getSource() == exit) {
133                 dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
134             }
135         };
136         exit.addActionListener(actionListener);
137         show.addActionListener(actionListener);
138         popupMenu.add(show);
139         popupMenu.add(exit);
140         TrayIcon trayIcon = new TrayIcon(image, "系统托盘", popupMenu);
141         trayIcon.setImageAutoSize(true);
142         try {
143             systemTray.add(trayIcon);
144         } catch (AWTException e) {
145             logger.error("add icon to tray failed");
146         }
147         trayIcon.addMouseListener(new MouseAdapter() {
148             @Override
149             public void mouseClicked(MouseEvent e) {
150                 if (e.getClickCount() == 2) {
151                     setExtendedState(JFrame.NORMAL);
152                     setVisible(true);
153                 }
154             }
155         });
156     }
157 
158     private void setMenuBar() {
159         menuBar = new JMenuBar();
160         setJMenuBar(menuBar);
161 
162         createReverseMenu();
163 
164         createAndroidMenu();
165 
166         createFileMenu();
167 
168         createConvertMenu();
169 
170         createHelpMenu();
171     }
172 
173     private void createHelpMenu() {
174         JMenu helpMenu = new JMenu(bundle.getString("help.title"));
175         menuBar.add(helpMenu);
176 
177         JMenuItem settingsMenuItem = new JMenuItem(bundle.getString("help.settings.title"));
178         settingsMenuItem.addActionListener(new ChangeMenuToPanelListener(SettingsPanel.class, settingsMenuItem.getText()));
179         helpMenu.add(settingsMenuItem);
180 
181         JMenuItem feedbackMenuItem = new JMenuItem(bundle.getString("help.feedback.title"));
182         feedbackMenuItem.addActionListener(new ChangeMenuToUrlListener(Constant.URL_FEEDBACK));
183         helpMenu.add(feedbackMenuItem);
184 
185         JMenuItem checkUpdateMenuItem = new JMenuItem(bundle.getString("help.checkupdate.title"));
186         checkUpdateMenuItem.addActionListener(new CheckUpdateActionListener(this));
187         helpMenu.add(checkUpdateMenuItem);
188 
189         JMenuItem contributeMenuItem = new JMenuItem(bundle.getString("help.contribute.title"));
190         contributeMenuItem.addActionListener(new ChangeMenuToUrlListener(Constant.URL_CONTRIBUTE));
191         helpMenu.add(contributeMenuItem);
192 
193         JMenuItem aboutMenuItem = new JMenuItem(bundle.getString("help.about.title"));
194         aboutMenuItem.addActionListener(new ChangeMenuToPanelListener(AboutPanel.class, aboutMenuItem.getText()));
195         helpMenu.add(aboutMenuItem);
196     }
197 
198     private void createFileMenu() {
199         JMenu fileMenu = new JMenu(bundle.getString("file.title"));
200         menuBar.add(fileMenu);
201 
202         JMenuItem osConvertMenuItem = new JMenuItem(bundle.getString("file.os.convert.title"));
203         osConvertMenuItem.addActionListener(new ChangeMenuToPanelListener(OsConvertPanel.class, osConvertMenuItem.getText()));
204         fileMenu.add(osConvertMenuItem);
205 
206         JMenuItem encodeConvertMenuItem = new JMenuItem(bundle.getString("file.encode.convert.title"));
207         encodeConvertMenuItem.addActionListener(new ChangeMenuToPanelListener(EncodeConvertPanel.class, encodeConvertMenuItem.getText()));
208         fileMenu.add(encodeConvertMenuItem);
209 
210         JMenuItem zhConvertMenuItem = new JMenuItem(bundle.getString("file.zh.convert.title"));
211         zhConvertMenuItem.addActionListener(new ChangeMenuToPanelListener(ZhConvertPanel.class, zhConvertMenuItem.getText()));
212         fileMenu.add(zhConvertMenuItem);
213 
214         JMenuItem duplicateFindMenuItem = new JMenuItem(bundle.getString("file.duplicate.title"));
215         duplicateFindMenuItem.addActionListener(new ChangeMenuToPanelListener(DuplicateSearchPanel.class, duplicateFindMenuItem.getText()));
216         fileMenu.add(duplicateFindMenuItem);
217 
218         JMenuItem batchRenameMenuItem = new JMenuItem(bundle.getString("file.batch.rename.title"));
219         batchRenameMenuItem.addActionListener(new ChangeMenuToPanelListener(BatchRenamePanel.class, batchRenameMenuItem.getText()));
220         fileMenu.add(batchRenameMenuItem);
221 
222         JMenuItem checkSumMenuItem = new JMenuItem(bundle.getString("file.check.summary.title"));
223         checkSumMenuItem.addActionListener(new ChangeMenuToPanelListener(ChecksumPanel.class, checkSumMenuItem.getText()));
224         fileMenu.add(checkSumMenuItem);
225 
226         JMenuItem recoveryMenuItem = new JMenuItem(bundle.getString("file.password.recovery.title"));
227         recoveryMenuItem.addActionListener(new ChangeMenuToPanelListener(RecoveryPanel.class, recoveryMenuItem.getText()));
228         fileMenu.add(recoveryMenuItem);
229     }
230 
231     private void createConvertMenu() {
232         JMenu convertMenu = new JMenu(bundle.getString("convert.title"));
233         menuBar.add(convertMenu);
234 
235         JMenuItem timeConvertMenuItem = new JMenuItem(bundle.getString("convert.time.title"));
236         timeConvertMenuItem.addActionListener(new ChangeMenuToPanelListener(TimeConvertPanel.class, timeConvertMenuItem.getText()));
237         convertMenu.add(timeConvertMenuItem);
238 
239         JMenuItem colorConvertMenuItem = new JMenuItem(bundle.getString("convert.color.title"));
240         colorConvertMenuItem.addActionListener(new ChangeMenuToPanelListener(ColorConvertPanel.class, colorConvertMenuItem.getText()));
241         convertMenu.add(colorConvertMenuItem);
242 
243         JMenuItem colorPickerMenuItem = new JMenuItem(bundle.getString("picker.color.title"));
244         colorPickerMenuItem.addActionListener(new ChangeMenuToPanelListener(ColorPickerPanel.class, colorPickerMenuItem.getText()));
245         convertMenu.add(colorPickerMenuItem);
246 
247         JMenuItem baseConvertMenuItem = new JMenuItem(bundle.getString("convert.base.title"));
248         baseConvertMenuItem.addActionListener(new ChangeMenuToPanelListener(BaseConvertPanel.class, baseConvertMenuItem.getText()));
249         convertMenu.add(baseConvertMenuItem);
250 
251         JMenuItem unicodeConvertMenuItem = new JMenuItem(bundle.getString("convert.unicode.title"));
252         unicodeConvertMenuItem.addActionListener(new ChangeMenuToPanelListener(Zh2UnicodeConvertPanel.class, unicodeConvertMenuItem.getText()));
253         convertMenu.add(unicodeConvertMenuItem);
254 
255         JMenuItem relationShipConvertMenuItem = new JMenuItem(bundle.getString("convert.relationship.title"));
256         relationShipConvertMenuItem.addActionListener(new ChangeMenuToPanelListener(RelationShipConvertPanel.class, relationShipConvertMenuItem.getText()));
257         convertMenu.add(relationShipConvertMenuItem);
258 
259         JMenuItem protobufConvertMenuItem = new JMenuItem(bundle.getString("convert.protobuf.title"));
260         protobufConvertMenuItem.addActionListener(new ChangeMenuToPanelListener(ProtobufConvertPanel.class, protobufConvertMenuItem.getText()));
261         convertMenu.add(protobufConvertMenuItem);
262     }
263 
264     private void createAndroidMenu() {
265         JMenu androidMenu = new JMenu(bundle.getString("android.title"));
266         menuBar.add(androidMenu);
267 
268         JMenuItem i18nAddMenuItem = new JMenuItem(bundle.getString("android.i18n.add.title"));
269         i18nAddMenuItem.addActionListener(new ChangeMenuToPanelListener(I18nAddPanel.class, i18nAddMenuItem.getText()));
270         androidMenu.add(i18nAddMenuItem);
271 
272         JMenuItem i18nFindLongestMenuItem = new JMenuItem(bundle.getString("android.i18n.longest.title"));
273         i18nFindLongestMenuItem.addActionListener(new ChangeMenuToPanelListener(I18nFindLongestPanel.class, i18nFindLongestMenuItem.getText()));
274         androidMenu.add(i18nFindLongestMenuItem);
275 
276         JMenuItem i18nRemoveMenuItem = new JMenuItem(bundle.getString("android.i18n.remove.title"));
277         i18nRemoveMenuItem.addActionListener(new ChangeMenuToPanelListener(I18nRemovePanel.class, i18nRemoveMenuItem.getText()));
278         androidMenu.add(i18nRemoveMenuItem);
279 
280         JMenuItem screenShotMenuItem = new JMenuItem(bundle.getString("android.screenshot.title"));
281         screenShotMenuItem.addActionListener(new ChangeMenuToPanelListener(ScreenShotPanel.class, screenShotMenuItem.getText()));
282         screenShotMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK));
283         androidMenu.add(screenShotMenuItem);
284 
285         JMenuItem monkeyMenuItem = new JMenuItem(bundle.getString("android.monkey.title"));
286         monkeyMenuItem.addActionListener(new ChangeMenuToPanelListener(MonkeyPanel.class, monkeyMenuItem.getText()));
287         androidMenu.add(monkeyMenuItem);
288 
289         JMenuItem dumpsysAlarmMenuItem = new JMenuItem(bundle.getString("android.dumpsys.alarm.title"));
290         dumpsysAlarmMenuItem.addActionListener(new ChangeMenuToPanelListener(DumpsysAlarmPanel.class, dumpsysAlarmMenuItem.getText()));
291         androidMenu.add(dumpsysAlarmMenuItem);
292     }
293 
294     private void createReverseMenu() {
295         JMenu reverseMenu = new JMenu(bundle.getString("reverse.title"));
296         reverseMenu.setMnemonic(KeyEvent.VK_R);
297         menuBar.add(reverseMenu);
298 
299         JMenuItem apktoolMenuItem = new JMenuItem(bundle.getString("reverse.apktool.title"), KeyEvent.VK_D);
300         apktoolMenuItem.addActionListener(new ChangeMenuToPanelListener(ApktoolPanel.class, apktoolMenuItem.getText()));
301         reverseMenu.add(apktoolMenuItem);
302 
303         JMenuItem apkSignMenuItem = new JMenuItem(bundle.getString("reverse.apksigner.title"));
304         apkSignMenuItem.addActionListener(new ChangeMenuToPanelListener(ApkSignerPanel.class, apkSignMenuItem.getText()));
305         reverseMenu.add(apkSignMenuItem);
306 
307         JMenuItem jDMenuItem = new JMenuItem(bundle.getString("reverse.jd.gui.title"));
308         jDMenuItem.addActionListener(new ChangeMenToPluginJdListener());
309         reverseMenu.add(jDMenuItem);
310 
311         JMenuItem luytenMenuItem = new JMenuItem(bundle.getString("reverse.luyten.title"));
312         luytenMenuItem.addActionListener(new ChangeMenuToPluginLuytenListener());
313         reverseMenu.add(luytenMenuItem);
314 
315         JMenuItem jdDuoMenuItem = new JMenuItem(bundle.getString("reverse.jd.duo.title"));
316         jdDuoMenuItem.addActionListener(new ChangeMenuToPluginJdDuoListener());
317         reverseMenu.add(jdDuoMenuItem);
318 
319         JMenuItem jADXMenuItem = new JMenuItem(bundle.getString("reverse.jadx.title"));
320         jADXMenuItem.addActionListener(new ChangeMenuToPluginJadxListener());
321         reverseMenu.add(jADXMenuItem);
322 
323         JMenuItem aXMLPrinter = new JMenuItem(bundle.getString("reverse.axmlprinter.title"));
324         aXMLPrinter.addActionListener(new ChangeMenuToPanelListener(AxmlPrinterPanel.class, aXMLPrinter.getText()));
325         reverseMenu.add(aXMLPrinter);
326     }
327 
328     class ChangeMenuToPanelListener implements ChangeMenuListener {
329 
330         Class<? extends EasyPanel> easyPanelClass;
331 
332         EasyPanel panel = null;
333 
334         String title;
335 
336         public ChangeMenuToPanelListener(Class<? extends EasyPanel> easyPanelClass, String title) {
337             this.easyPanelClass = easyPanelClass;
338             this.title = title;
339             panel = createEasyPanel();
340         }
341 
342         @Override
343         public boolean isNeedPreChangeMenu() {
344             return panel.isNeedPreChangeMenu();
345         }
346 
347         @Override
348         public void onPreChangeMenu(IPreChangeMenuCallBack callBack) {
349             if (panel instanceof PluginPanel pluginPanel) {
350                 pluginPanel.preparePlugin(
351                         new ChangeMenuPreparePluginController(
352                                 pluginPanel.getPluginFilename(), pluginPanel.isPluginNeedUnzip(), callBack));
353             }
354         }
355 
356         @Override
357         public void onChangeMenu() {
358             contentPane.removeAll();
359             contentPane.add(Box.createVerticalGlue());
360             panel.init();
361             panel.setBorder(BorderFactory.createTitledBorder(title));
362             contentPane.add(panel);
363             logger.info("Panel changed: " + panel.getClass().getSimpleName());
364             contentPane.add(Box.createVerticalGlue());
365             contentPane.revalidate();
366             contentPane.repaint();
367             refreshSizeAndLocation();
368         }
369 
370         private EasyPanel createEasyPanel() {
371             if (easyPanelClass == null) {
372                 return new EasyPanel();
373             }
374             EasyPanel retEasyPanel = null;
375             try {
376                 retEasyPanel = easyPanelClass.getDeclaredConstructor().newInstance();
377             } catch (InstantiationException | IllegalAccessException | InvocationTargetException |
378                      NoSuchMethodException e) {
379                 logger.info("createEasyPanel failed: {}", e.getMessage());
380             }
381             return Objects.requireNonNullElseGet(retEasyPanel, EasyPanel::new);
382         }
383     }
384 }
385 
386